﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;

using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Spreadsheets;

namespace DataSources.Holder
{
    public class GoogleWorksheets : DataSources.GoogleWorksheets, IDataHolder
    {
        public event EventHandler EntryChanged;

        public GoogleWorksheets(SpreadsheetsService service, DataSources.GoogleSpreadsheets owner, string ownerCurrentEntryHash) :
            base(service, owner, ownerCurrentEntryHash)
        {
        }

        public IDataHolder GetChildDataSource(string entryHash)
        {
            if (this.worksheets.Contains(entryHash))
                return new GoogleCells(this.service, this, entryHash);
            return null;
        }

        public Size GetSize()
        {
            return Size.Empty;
        }

        public Hashtable GetEntries()
        {
            return this.worksheets;
        }

        public void AddRowsForCell(string entryHash, uint cellCoordinateY)
        {
            // insert blank rows first
            WorksheetQuery queryWorksheet = new WorksheetQuery(CurrentSpreadsheet.feedUri);
            WorksheetFeed feedWorksheet = service.Query(queryWorksheet);

            // TODO: figure out more buitiful method to find entry with current id
            foreach (AtomEntry entry in feedWorksheet.Entries)
            {
                if (entry.Id.AbsoluteUri == entryHash)
                {
                    WorksheetEntry worksheetEntry = entry as WorksheetEntry;
                    worksheetEntry.Rows = cellCoordinateY;

                    try
                    {
                        worksheetEntry.Update();
                    }
                    catch (Exception ex)
                    {
                        worksheetEntry = EntryResolveConflict(entryHash, cellCoordinateY, ex);
                    }

                    // TODO: avoid copy-paste!
                    // Get the cells feed URI
                    AtomLink cellsLink = worksheetEntry.Links.FindService(
                        GDataSpreadsheetsNameTable.CellRel,
                        AtomLink.ATOM_TYPE
                    );
                    // Get the list feed URI
                    AtomLink listLink = worksheetEntry.Links.FindService(
                        GDataSpreadsheetsNameTable.ListRel,
                        AtomLink.ATOM_TYPE
                    );
                    // Create an item to store the title and the worksheet's feed URI
                    worksheets[entryHash] = new WorksheetInfo(
                        worksheetEntry.Title.Text +
                        " (Rows:" + ((WorksheetEntry)worksheetEntry).RowCount.Count +
                        ", Cols:" + ((WorksheetEntry)worksheetEntry).ColCount.Count + ")",
                        cellsLink.HRef.Content,
                        listLink.HRef.Content,
                        worksheetEntry
                    );
                    break;
                }
            }
        }

        private WorksheetEntry EntryResolveConflict(string entryHash, uint cellCoordinateY, Exception ex)
        {
            // TODO: implement conflict resolvings
            MessageBox.Show(
                "Can not insert row " + entryHash + " in position " + cellCoordinateY + ":\n\r" + ex.ToString(),
                "Conflict. Refresh code table."
            );
            return null;
        }

        public void Submit(string entryHash, object inputData)
        {
            // TODO: implement - when user adds new rows
        }

        public void Request(string entryHash)
        {
            // TODO: implement - when columns/rows were added/removed on server
            //OnEntryChanged(EventArgs.Empty);
        }

        protected virtual void OnEntryChanged(EventArgs e)
        {
            EventHandler handler = this.EntryChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        /*
        public void ReloadAll()
        {
            // TODO: test updated time - actual and cached
            cells = null;
            cellEntries = null;
            LoadBlocks();
            OnTableChanged(EventArgs.Empty);
        }

        public void SubmitAll(Hashtable stringHashtable)
        {
            // TODO: reload cell before submit

            // delete cells
            foreach (DictionaryEntry cahcedEntry in cells)
            {
                string hash = cahcedEntry.Key as string;
                if (!stringHashtable.ContainsKey(cahcedEntry.Key))
                {
                    SubmitBlock(hash, string.Empty);
                }
            }

            // update and add cells
            foreach (DictionaryEntry inputEntry in stringHashtable)
            {
                string hash = inputEntry.Key as string;
                string inputEntryText = inputEntry.Value as string;
                SubmitBlock(hash, inputEntryText);
            }
        }
        */
    }
}
